#ifndef __SOLO_JOB_HPP__
#define __SOLO_JOB_HPP__
#include "rwmutex.hpp"
#include "lock.hpp"

namespace vpm
{
    namespace utils
    {
        template <class T = void* >
            class SoloJob
            {
                enum JobState
                {
                    JOB_NONE,
                    JOB_TAKEN,
                    JOB_DONE,
                };
                public:
                    SoloJob()
                    {
                        m_jobState = JOB_NONE;
                    }

                    bool take() //take and do the job  
                    {
                        WriteLock lock(m_mutex);
                        if (m_jobState == JOB_NONE)
                        {
                            m_jobState = JOB_TAKEN; 
                            return true; 
                        }
                        return false; 
                    }

                    bool take(T & owner)
                    {
                        m_owner = owner; 
                        return take();
                    }

                    void untake()
                    {
                        WriteLock lock(m_mutex);
                        m_jobState = JOB_NONE; 
                    }

                    T owner()
                    {
                        if (m_jobState == JOB_NONE)
                        {
                            return m_emptyOwner; 
                        }

                        return m_owner; 
                    }

                    bool is_taken()
                    {
                        ReadLock lock(m_mutex);
                        return (m_jobState == JOB_TAKEN);
                    }

                    bool is_done()
                    {
                        ReadLock lock(m_mutex);
                        return (m_jobState == JOB_DONE);
                    }

                    void done()
                    {
                        WriteLock lock(m_mutex);
                        m_jobState = JOB_DONE; 
                    }

                    void reset()//reset the job state 
                    {
                        WriteLock lock(m_mutex);
                        m_jobState = JOB_DONE; 
                    }

                private:
                    T m_owner;
                    T m_emptyOwner; 
                    RWMutex m_mutex; 
                    JobState m_jobState;
            };
    }
}

#endif //
